home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Font Handler / ResolveShapeFonts.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  27.3 KB  |  967 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        ResolveShapeFonts.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains code for the Font Handler for
  6.                         ResolveShapeFonts -- The routine that
  7.                         remaps glyphs to printer glyph codes
  8.                         and child fonts.
  9.  
  10.      Version:    Technology:    Quickdraw GX 1.1.x
  11.       
  12.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  13. */
  14.  
  15. #include <MacMemory.h>
  16. #include <String.h>
  17. #include "GXToPSBuildConfig.h"
  18. #include <GXExceptions.h>
  19. #include "IOUtilities.h"
  20. #include "GXPrintingUniverse.h"
  21. #include <Collections.h>
  22.  
  23. #include "FontDatabase.h"
  24. #include "FontHandler.h"
  25. #include "FontHandlerPrivate.h"
  26. #include "FontHandlerVariations.h"
  27. #include "GXGraphics.h"
  28. #include "GXLayout.h"
  29.  
  30.  
  31. /*** Constants for which workspace handles will be used for what data ***/
  32. #define kStyleHandle 0
  33. #define kRunHandle 1
  34. #define kTextHandle 2
  35. #define kGlyphHandle 3
  36. #define kEncodedGlyphHandle 4
  37.  
  38. #define kUnTaggedStyle -1
  39.  
  40.  
  41. #ifdef resumeLabel
  42.     #undef resumeLabel
  43. #endif
  44. #define resumeLabel(exception)
  45.  
  46. /*****************************************
  47.  
  48.     Function: FHMapGlyph
  49.     
  50.     Function takes a document font/glyph combination
  51.     and maps it to a printer font/glyph comgination.
  52.     
  53.     hFHRec:                        --> Handle to the font handler record.
  54.     theFont:                    --> document font reference.
  55.     theGlyph:                    --> document glyph ID.
  56.     printerIndex:            <-- printer font index to use.
  57.     printerCode:            <-- printer code to use.
  58.     twoByteCode                <-- One or two byte code?
  59.     
  60.     If this returns collectionItemNotFoundErr or 
  61.         collectionIndexRangeErr than it means the
  62.         there is no record of this glyph in this
  63.         font in the printer-font records.  The
  64.         glyph must have been added during imaging
  65.         time.  The client should handle this.
  66.         
  67. ******************************************/
  68. OSErr FHMapGlyph(TFontHandlerHdl hFHRec, fhFont theFont, short theGlyph, long *printerIndex, short *printerCode, Boolean *twoByteCode);
  69. OSErr FHMapGlyph(TFontHandlerHdl hFHRec, fhFont theFont, short theGlyph, long *printerIndex, short *printerCode, Boolean *twoByteCode)
  70.     {
  71.         OSErr                                status;
  72.         TPrinterFontRec            *printerFont;            // a pointer to a printer font record.
  73.         Boolean                            found;                        // Found the glyph?        
  74.         short                                prIndex;                    // printer font index.    
  75.         long                                offset;                        // Offset into data for printer font.
  76.         
  77.         /***** Find the printer font that contains this glyph ******/
  78.  
  79.         prIndex = -1;
  80.         do {
  81.                     
  82.             /*** Get the next printer font for this document font ***/
  83.  
  84.             ++prIndex;
  85.             status = FHGetIndexedPrinterFont(hFHRec, theFont, prIndex, &printerFont, &offset);        // watch for bug: if hFHRec moves, printerFont is invalid
  86.             nrequire(status, failed_GetItem);
  87.                         
  88.             /** Check to see if this glyph is in this printer font **/
  89.             
  90.             found = BITTST(printerFont->glyphUsage, theGlyph);        
  91.         
  92.         } while (!found);
  93.                 
  94.         /***** If the glyph is in a font that cannot be handled by the printer return appropriate error ****/
  95.         
  96.         if (printerFont->info & fontCantBeUsed)
  97.             return(no_outline_font_found);
  98.         
  99.         /***** We found the glyph, get the printer code ******/
  100.         
  101.         *printerIndex = prIndex;
  102.         
  103.         if (printerFont->info & fontCantBeRencoded) {
  104.         
  105.             unsigned short            *charCodes = (unsigned short*)*(printerFont->glyphToCharCodeMap);
  106.             *printerCode = charCodes[theGlyph];
  107.                         
  108.             if (*printerCode & 0xFF00)
  109.                 *twoByteCode = true;                // First byte of short is non-zero, means 2 bytes.
  110.             else
  111.                 *twoByteCode = false;
  112.         
  113.         } else {
  114.         
  115.             *printerCode = FHGetGlyphHash(theGlyph, printerFont->printerFontCodes);
  116.             
  117.             if (printerFont->info & fontIsTwoByteMember) {
  118.  
  119.                 /** Make two byte code by combining printerIndex and printerCode **/
  120.                 
  121.                 *twoByteCode = true;
  122.                 *printerCode |= (prIndex << 8);
  123.                 *printerIndex = kTwoByteGroupIndex;
  124.                 
  125.             } else {
  126.                 
  127.                 *twoByteCode = false;
  128.                 
  129.             }//end if
  130.             
  131.         }//end if
  132.                 
  133. failed_GetItem:
  134.  
  135. #if DEBUGLEVEL > 1
  136.         if (status != noErr) {
  137.             long dbIndex;
  138.             dprintf(  trace, "couldn't map, theFont: %d theGlyph: %d", theFont, theGlyph);
  139.             dprintf(  trace, "Real font: %d, dbIndex: %d", FHGetSnapShotFont(hFHRec, theFont, &dbIndex), dbIndex);
  140.             dprintf(notrace, "If you are not running an extension, then this is a bug");
  141.         }//end if
  142. #endif
  143.  
  144.         return(status);
  145.     
  146.     }//FHMapGlyph
  147.  
  148.  
  149. //<FF>
  150. /*************************************************
  151.  
  152.     Function FHSetTextTag:
  153.     
  154.     Function adds the tag to the shape containing the
  155.     printer mapped text data and the bit array for 1or2 byte codes.
  156.     
  157. **************************************************/
  158. OSErr FHSetTextTag(gxShape theShape, unsigned char *textData, long size, unsigned long *twoBits, long nChars);
  159. OSErr FHSetTextTag(gxShape theShape, unsigned char *textData, long size, unsigned long *twoBits, long nChars)
  160.     {
  161.         gxTag            theTag;
  162.  
  163.         theTag = GXNewTag(fhTextDataTag, size, textData);
  164.         GXSetShapeTags(theShape, fhTextDataTag, 0, 0, 1, &theTag);
  165.         GXDisposeTag(theTag);
  166.         
  167.         if (twoBits != nil) {
  168.         
  169.             theTag = GXNewTag(fh1or2byteTag, 4 * ( (nChars + 31) / 32 ), twoBits);
  170.             GXSetShapeTags(theShape, fh1or2byteTag, 0, 0, 1, &theTag);
  171.             GXDisposeTag(theTag);
  172.                         
  173.         }//end if
  174.         
  175.         return(GXGetGraphicsError(nil));
  176.         
  177.     }//FHSetTextTag
  178.     
  179.     
  180.     
  181. //<FF>
  182. /*************************************************
  183.  
  184.     Function:  FHAddStyleRun:
  185.     
  186.     Function adds a style run to the array of styles
  187.     and style runs. Grows handles if necessary.  
  188.             
  189.     hFHRec:                Font handler record handle.
  190.     theStyle:            A style to add.
  191.     index:                index of style to add. (0based)
  192.     
  193. **************************************************/
  194. OSErr    FHAddStyleRun(TFontHandlerHdl hFHRec, gxStyle theStyle, long index);
  195. OSErr    FHAddStyleRun(TFontHandlerHdl hFHRec, gxStyle theStyle, long index)
  196.     {
  197.         OSErr                                status;        
  198.         Handle                            h;
  199.         gxStyle                            *aStyle;
  200.         short                                *aRun;
  201.         
  202.         status = FHSetWorkHandleSize(hFHRec, (index + 1) * sizeof(gxStyle), kStyleHandle, nil);
  203.         nrequire(status, failed_0);
  204.  
  205.         h = (*hFHRec)->workHandle[kStyleHandle];
  206.         
  207.         aStyle = (gxStyle*)(*h + index * sizeof(gxStyle));
  208.         *aStyle = theStyle;
  209.  
  210.         status = FHSetWorkHandleSize(hFHRec, (index + 1) * sizeof(short), kRunHandle, nil);        
  211.         nrequire(status, failed_1);
  212.  
  213.         h = (*hFHRec)->workHandle[kRunHandle];
  214.         
  215.         aRun = (short*)(*h + index * sizeof(short));
  216.  
  217. failed_1:
  218. failed_0:
  219.         return(status);
  220.     
  221.     }//FHAddStyleRun
  222.     
  223.  
  224. //<FF>
  225. /**************************************
  226.     
  227.     Function:  FHSetStylePrFontIndex
  228.     
  229.     Function tags a style with the printer font
  230.     index.  If there is a tag there, it replaces it.
  231.     
  232. ***************************************/
  233. OSErr FHSetStylePrFontIndex(gxStyle theStyle, long printerFontIndex);
  234. OSErr FHSetStylePrFontIndex(gxStyle theStyle, long printerFontIndex)
  235.     {
  236.         OSErr            status;
  237.         gxTag            theTag;
  238.             
  239.         theTag = GXNewTag(prFontIndexTag, 4, &printerFontIndex);
  240.                 
  241.         if (GXGetStyleTags(theStyle, prFontIndexTag, 1, 1, nil) ) {
  242.         
  243.             GXSetStyleTags(theStyle, prFontIndexTag, 1, 1, 1, &theTag);
  244.             
  245.         } else {
  246.         
  247.             GXSetStyleTags(theStyle, prFontIndexTag, 0, 0, 1, &theTag);
  248.                         
  249.         }//end if
  250.                     
  251.         GXDisposeTag(theTag);
  252.                 
  253.         status = GXGetGraphicsError(nil);
  254.         
  255.         return(status);
  256.     
  257.     }//FHSetStylePrFontIndex
  258.     
  259.  
  260. /****************************************
  261.  
  262.     Function: FHInitStylePrFontIndex
  263.     
  264.     Function initializes the printer font index tag
  265.     on a style to kUnTaggedStyle.
  266.     
  267. *****************************************/
  268. OSErr FHInitStylePrFontIndex(gxStyle theStyle);
  269. OSErr FHInitStylePrFontIndex(gxStyle theStyle)
  270.     {
  271.         OSErr            status;
  272.         status = FHSetStylePrFontIndex(theStyle, kUnTaggedStyle);
  273.         
  274.         return(status);
  275.         
  276.     }//FHInitStylePrFontIndex
  277.  
  278.  
  279. //<FF>
  280. /*************************************************
  281.  
  282.     Function: FHResolveGlyphShape
  283.     
  284.     Resolve the codes and fonts for a glyph shape.
  285.     
  286. **************************************************/
  287. OSErr    FHResolveGlyphShape(TFontHandlerHdl hFHRec, gxShape theShape);
  288. OSErr    FHResolveGlyphShape(TFontHandlerHdl hFHRec, gxShape theShape)
  289.     {
  290.         OSErr                            status;
  291.         register short        idx;
  292.         short                            *pRuns, *pRunLength;
  293.         gxStyle                        *pStyles, *walkStyles;
  294.         gxStyle                        shapeStyle, aStyle;
  295.         unsigned char            *textData;
  296.         unsigned char            *newTextData, *inNewTextData;
  297.         short                            *pGlyphCodes, newCode;
  298.         unsigned short        *pRunGlyphs;
  299.         Handle                        h, hStyles, hRuns;                                                                // new runs and styles.
  300.         long                            size;
  301.         long                            nChars, nRuns, byteCount, /*charCounter,*/ newRunIndex, totalRuns;
  302.         long                            i, j, prFontIndex, lastPrIndex;
  303.         Boolean                        twoByteCode;
  304.         unsigned long            *pTwoByteGlyphBits;            // bit array for 1 or 2 byte printer codes.
  305.         unsigned long            *inTwoByteBits;                    // Pointer into bit array.
  306.         unsigned long            twoByteMask;                        // Mask for making bit array.
  307.         gxShapeAttribute    theAttributes;
  308.         fhFont                        theFont;
  309.         gxFont                        theRealFont;
  310.         gxFontPlatform        thePlatform;
  311.         gxFontLanguage        theLanguage;
  312.         gxFontScript            theScript;
  313.                 
  314.         shapeStyle = GXGetShapeStyle(theShape);
  315.         theAttributes = GXGetShapeAttributes(theShape);
  316.         
  317.         /**** Get the glyph data into our handle ****/
  318.         byteCount = GXGetGlyphs(theShape, &nChars, nil, nil, nil, nil, &nRuns, nil, nil);
  319.         
  320.         size =     byteCount +                             // For source text data;
  321.                         nRuns * (
  322.                             sizeof(short) +                 // for source runs
  323.                             sizeof(gxStyle)                    // for source styles
  324.                         ) +
  325.                         nChars * (
  326.                             sizeof(short) +                    // for new encoded glyphs.
  327.                             sizeof(short)    +                    // for glyph code data from ApplyFontEncoding
  328.                             4*((nChars + 31) / 32)    // for 1or2byte bit array
  329.                         );
  330.         
  331.         status = FHSetWorkHandleSize(hFHRec, size, kTextHandle, &h);
  332.         nrequire(status, failed_SetSize1);
  333.         HLockHi(h);
  334.         
  335.         /** Get the glyph data **/
  336.         {
  337.             register Ptr p = *h;
  338.             textData = (unsigned char*)p;                     p += byteCount;
  339.             pRuns = (short*)p;                                             p += nRuns * sizeof(short);
  340.             pStyles = (gxStyle*)p;                                    p += nRuns * sizeof(gxStyle);
  341.             newTextData = (unsigned char*)p;                p += nChars * sizeof(short);
  342.             pGlyphCodes = (short*)p;                                p += nChars * sizeof(short);
  343.             pTwoByteGlyphBits = (unsigned long*)p;
  344.         }
  345.         GXGetGlyphs(theShape, nil, textData, nil, nil, nil, nil, pRuns, pStyles);
  346.         
  347.         /** Initialize size for new styles and runs to be current style and run size **/
  348.         
  349.         status = FHSetWorkHandleSize(hFHRec, nRuns * sizeof(gxStyle), kStyleHandle, &hStyles);
  350.         nrequire(status, failed_SetSize2);
  351.         
  352.         status = FHSetWorkHandleSize(hFHRec, nRuns * sizeof(short), kRunHandle, &hRuns);
  353.         nrequire(status, failed_SetSize3);
  354.         HLock(hRuns);
  355.         
  356.         /** Make sure each style has an initial printer font index **/
  357.         walkStyles = pStyles;
  358.         for (idx = nRuns - 1; idx >= 0; --idx) {
  359.         
  360.             aStyle = *walkStyles++;
  361.             if (aStyle == nil)
  362.                 aStyle = shapeStyle;
  363.                 
  364.             status = FHInitStylePrFontIndex(aStyle);
  365.             nrequire(status, failed_InitStyles);
  366.             
  367.         }//end for
  368.         
  369.         /****************************************
  370.             Re Encode each style run,
  371.             Generate new runs if necessary because
  372.             of child fonts
  373.         *****************************************/
  374.         //charCounter = 1;
  375.         size = 0;
  376.         inNewTextData = newTextData;
  377.         inTwoByteBits = pTwoByteGlyphBits;
  378.         twoByteMask = 0x80000000;
  379.         totalRuns = 0;
  380.         
  381.         for (i = 0; i < nRuns; ++i) {
  382.         
  383.             /*** Make sure the data for this style run is in glyph platform ***/
  384.             if (*pStyles == nil)
  385.                 *pStyles = shapeStyle;
  386.                 
  387.             
  388.             status = _FontHandlerGetStyleFont((TFontHandlerContext)hFHRec, *pStyles, &theFont);
  389.             nrequire(status, failed_FHGetFont);
  390.             
  391.             theRealFont = FHgxGetStyleFont(*pStyles);
  392.             thePlatform = GXGetStyleEncoding(*pStyles, &theScript, &theLanguage);
  393.             
  394.             if ( (!(theAttributes & gxIgnorePlatformShape )) && (thePlatform != gxGlyphPlatform) ) {
  395.             
  396.                 long idx, byteLen, glyphsEncoded;
  397.                 
  398.                 pRunGlyphs = (unsigned short*) pGlyphCodes;
  399.                 idx = GXFindFontEncoding(theRealFont, thePlatform, theScript, theLanguage);
  400.                 check(idx);
  401.  
  402.                 byteLen = *pRuns * 2;
  403.                 glyphsEncoded = GXApplyFontEncoding(theRealFont, idx, &byteLen, textData, *pRuns, pRunGlyphs, nil);
  404.                 check(glyphsEncoded == *pRuns);
  405.                 
  406.                 textData += byteLen;            // Increment pointer to next run of text.
  407.  
  408.             } else {
  409.             
  410.                 pRunGlyphs = (unsigned short*)textData;                // data is already in glyph format.
  411.                 textData += *pRuns * sizeof(short);                        // Increment pointer to next run of text.
  412.                 
  413.             }//end if
  414.             
  415.             /**** Now the data for this run is in glyphPlatform and pointed to by pRunGlyphs ******/
  416.             
  417.             lastPrIndex = FHGetStylePrFontIndex(*pStyles);        // Initialize last to current.
  418.             
  419.             newRunIndex = 0;                                                    // newRunIndex is the index of the new run based on original
  420.             for (j = 0; j < *pRuns; ++j) {
  421.             
  422.                 status = FHMapGlyph(hFHRec, theFont, *pRunGlyphs++, &prFontIndex, &newCode, &twoByteCode);
  423.                 nrequire(status, failed_MapGlyph);
  424.             
  425.                 /** Put the recoded data into the block **/
  426.                 
  427.                 if (twoByteCode) {
  428.                 
  429.                     *(short*)inNewTextData = newCode;
  430.                     inNewTextData += sizeof(short);
  431.                     size += sizeof(short);
  432.                     *inTwoByteBits |= twoByteMask;                // turn on bit for two-byte code.
  433.                 
  434.                 } else {
  435.                 
  436.                     *inNewTextData++ = (unsigned char)newCode;
  437.                     ++size;
  438.                     *inTwoByteBits &= ~twoByteMask;            // turn off bit for two byte mask.
  439.                 
  440.                 }//end if
  441.                 
  442.                 /** Advance the two byte mask and pointer **/
  443.                 if ( (twoByteMask >>= 1) == 0) {
  444.                     twoByteMask = 0x80000000;
  445.                     ++inTwoByteBits;
  446.                 }//end if
  447.                 
  448.                 /** Now see if we need start a mew run because printer font index changed **/
  449.                 /**            or first time in loop for this run **/
  450.                 
  451.                 if ( (prFontIndex != lastPrIndex) || (j == 0) ) {
  452.                                     
  453.                     /*************
  454.                         If the index is the same or the style is as yet untagged for this shape
  455.                         then use the style as is, otherwise we need to make a copy of the new
  456.                         one and tag it.
  457.                     **************/
  458.                     if ( (prFontIndex == lastPrIndex)  || (lastPrIndex == kUnTaggedStyle) )    
  459.                         aStyle = GXCloneStyle(*pStyles);
  460.                     else
  461.                         aStyle = GXCopyToStyle(nil, *pStyles);
  462.                     
  463.                     
  464.                     /** Add the new run to our array of runs and styles **/
  465.                     HUnlock(hRuns);                                                            // Unlock it so it can grow.
  466.                     status = FHAddStyleRun(hFHRec, aStyle, newRunIndex + totalRuns);
  467.                     nrequire(status, failed_AddRun);
  468.                     HLock(hRuns);                                                                // relock it so we can point into it.
  469.                     
  470.                     pRunLength = (short*)(*hRuns) + newRunIndex + totalRuns;            // Point to this run.
  471.                     *pRunLength = 1;                                                                                            // Initialize it to 1.
  472.                     ++newRunIndex;                
  473.                     
  474.                     if (prFontIndex != lastPrIndex) {
  475.     
  476.                         status = FHSetStylePrFontIndex(aStyle, prFontIndex);
  477.                         nrequire(status, failed_TagStyle);
  478.                         lastPrIndex = prFontIndex;
  479.     
  480.                     }//end if
  481.                 
  482.                 } else {                                        // printer font index stayed same, build up this run.
  483.  
  484.                     *pRunLength += 1;
  485.                     
  486.                 }//end if    
  487.                                             
  488.             }//end for
  489.         
  490.             totalRuns += newRunIndex;            // Add the number of new runs generated for this run to the total
  491.             //charCounter += *pRuns;                // increment charCounter for next call to GetGlyphParts.
  492.             ++pStyles;
  493.             ++pRuns;
  494.             
  495.         }//end for
  496.         
  497.         /** Put the new runs and styles in the glyph shape **/
  498.         
  499.         hStyles = (*hFHRec)->workHandle[kStyleHandle];
  500.         hRuns = (*hFHRec)->workHandle[kRunHandle];
  501.         
  502.         //dprintf(notrace, "chars: %d, runs: %X", nChars, *hRuns);
  503.         
  504.         /** In case gx graphics moves memory **/
  505.         
  506.         HLock(hStyles);
  507.         HLock(hRuns);
  508.         
  509.         GXSetGlyphParts(theShape, 1, nChars, nChars, nil, nil, nil, nil, (short*)*hRuns, (gxStyle*)*hStyles);
  510.         
  511.         /** Since SetGlyphParts increments owner counts, dispose of all styles we passed in **/
  512.         walkStyles = (gxStyle*)*hStyles;
  513.         for (idx = totalRuns - 1; idx >= 0; --idx)
  514.             GXDisposeStyle(*walkStyles++);
  515.         
  516.  
  517.         /** Put the tag on the shape containing the bytes for PostScript **/
  518.         
  519.         status = FHSetTextTag(theShape, newTextData, size, pTwoByteGlyphBits, nChars);
  520.         ncheck(status);
  521.  
  522. failed_TagStyle:
  523. failed_AddRun:
  524. failed_MapGlyph:
  525. failed_InitStyles:
  526. failed_FHGetFont:
  527.  
  528.         FHReleaseWorkspace(hFHRec, kRunHandle);
  529.         
  530. failed_SetSize3:
  531.  
  532.         FHReleaseWorkspace(hFHRec, kStyleHandle);
  533.  
  534. failed_SetSize2:
  535.  
  536.         FHReleaseWorkspace(hFHRec, kTextHandle);
  537.  
  538. failed_SetSize1:    
  539.  
  540.         return(status);
  541.         
  542.     }//FHResolveGlyphShape
  543.  
  544.  
  545.  
  546. //<FF>
  547. /*************************************************
  548.  
  549.     Function: FHResolveTextShape
  550.     
  551.     Resolve the codes and fonts for a text shape.
  552.     
  553. **************************************************/
  554. OSErr    FHResolveTextShape(TFontHandlerHdl hFHRec, gxShape theShape);
  555. OSErr    FHResolveTextShape(TFontHandlerHdl hFHRec, gxShape theShape)
  556.     {
  557.         OSErr                        status;
  558.         long                        size;                        // Number of bytes in text shape.
  559.         Handle                    hStyles;
  560.         Handle                    hRuns;
  561.         Handle                    hText;
  562.         Handle                    hGlyphs;
  563.         Handle                    newGlyphs;
  564.         long                        runIndex;
  565.         short                        *runLength;            // Pointer into handle of run lengths;
  566.         gxStyle                    aStyle, theStyle;
  567.         long                        charCount;
  568.         long                        idx;
  569.         long                        prFontIndex;        // Printer font index for the glyph.
  570.         long                        lastPrIndex;
  571.         short                        newCode;
  572.         unsigned char        *pText, *pNewText;
  573.         unsigned short    *pGlyphs;
  574.         fhFont                    theFont;
  575.         Boolean                    twoByteCode;
  576.         unsigned long        *pTwoByteGlyphBits;            // bit array for 1 or 2 byte printer codes.
  577.         unsigned long        *inTwoByteBits;                    // Pointer into bit array.
  578.         unsigned long        twoByteMask;                        // Mask for making bit array.
  579.         gxFontPlatform    thePlatform;
  580.         gxFontScript        theScript;
  581.         gxFontLanguage    theLanguage;
  582.         long                        dataSize;                // Size of new text data.
  583.         
  584.         size = GXGetText(theShape, &charCount, nil, nil);
  585.         if (size == 0) return(noErr);
  586.         
  587.         /** Size > 0, process the text **/
  588.  
  589.         theStyle = GXGetShapeStyle(theShape);
  590.         
  591.         status  = _FontHandlerGetStyleFont((TFontHandlerContext)hFHRec, theStyle, &theFont);
  592.         nrequire(status, failed_FHGetFont);
  593.         
  594.         thePlatform = GXGetStyleEncoding(theStyle, &theScript, &theLanguage);
  595.         
  596.         /** Handle for the shape's text and 1or2 byte bit array **/
  597.         status = FHSetWorkHandleSize(hFHRec, size + 4 * ( (charCount + 31) / 32), kTextHandle, &hText);
  598.         nrequire(status, failed_SetSize1);
  599.  
  600.         /** Handle for the glyph codes if it is not alread in glyph code format **/
  601.         if (thePlatform != gxGlyphPlatform) {
  602.         
  603.             status = FHSetWorkHandleSize(hFHRec, charCount * sizeof(short), kGlyphHandle, &hGlyphs);
  604.             nrequire(status, failed_SetSize1);
  605.             HLock(hGlyphs);
  606.             
  607.         }//end if
  608.  
  609.         /** Handle for the new encoded glyphs for the tag **/        
  610.         status = FHSetWorkHandleSize(hFHRec, 2 * charCount, kEncodedGlyphHandle, &newGlyphs);
  611.         nrequire(status, failed_SetSize2);
  612.         
  613.         hRuns = (*hFHRec)->workHandle[kRunHandle];
  614.         hStyles = (*hFHRec)->workHandle[kStyleHandle];
  615.         HLock(newGlyphs);
  616.         HLock(hText);
  617.         
  618.         /** Get the text data **/
  619.         pText = (unsigned char*)*hText;
  620.         pTwoByteGlyphBits = (unsigned long*)(pText + size);
  621.         GXGetText(theShape, nil, pText, nil);
  622.         
  623.         /** Convert it all to glyph codes **/
  624.         if (thePlatform != gxGlyphPlatform) {
  625.         
  626.             long        byteLen = size;
  627.             gxFont    theRealFont;
  628.             
  629.             theRealFont = FHGetSnapShotFont(hFHRec, theFont, nil);
  630.             
  631.             pGlyphs = (unsigned short*)*hGlyphs;
  632.             idx = GXFindFontEncoding(theRealFont, thePlatform, theScript, theLanguage);
  633.             check(idx);
  634.             dataSize = GXApplyFontEncoding(theRealFont, idx, &byteLen, pText, charCount, pGlyphs, nil );
  635.             check(dataSize == charCount);
  636.                         
  637.         } else {
  638.         
  639.             pGlyphs = (unsigned short*)pText;
  640.             
  641.         }//end if
  642.         
  643.         /**** Generate the printer codes and style runs ****/
  644.         
  645.         status = FHInitStylePrFontIndex(theStyle);
  646.         nrequire(status, failed_InitStyle);
  647.         
  648.         pNewText = (unsigned char*)*newGlyphs;
  649.         runIndex = 0;
  650.         aStyle = nil;
  651.         dataSize = 0;
  652.         lastPrIndex = FHGetStylePrFontIndex(theStyle);
  653.         inTwoByteBits = pTwoByteGlyphBits;
  654.         twoByteMask = 0x80000000;
  655.         
  656.         for (idx = 0; idx < charCount; ++idx) {
  657.                     
  658.             status = FHMapGlyph(hFHRec, theFont, *pGlyphs, &prFontIndex, &newCode, &twoByteCode);
  659.             nrequire(status, failed_MapGlyph);
  660.             
  661.             if (twoByteCode) {
  662.             
  663.                 *(short*)pNewText = newCode;
  664.                 pNewText += sizeof(short);
  665.                 dataSize += sizeof(short);
  666.                 *inTwoByteBits |= twoByteMask;                // turn on bit for two-byte code.
  667.             
  668.             } else {
  669.             
  670.                 *pNewText++ = (unsigned char)newCode;
  671.                 ++dataSize;
  672.                 *inTwoByteBits &= ~twoByteMask;            // turn off bit for two byte mask.
  673.             
  674.             }//end if
  675.             
  676.             /** Advance the two byte mask and pointer **/
  677.             if ( (twoByteMask >>= 1) == 0) {
  678.                 twoByteMask = 0x80000000;
  679.                 ++inTwoByteBits;
  680.             }//end if
  681.  
  682.             /** Determine if we need a new run becuase printer font index changed **/
  683.             /**     or the first time through the loop **/
  684.  
  685.             if ( (prFontIndex != lastPrIndex) || (idx == 0)) {
  686.                             
  687.                 if (runIndex == 0)
  688.                     aStyle = GXCloneStyle(theStyle);
  689.                 else
  690.                     aStyle = GXCopyToStyle(nil, theStyle);
  691.                 
  692.                 HUnlock(hRuns);                                                                        // Unlock it so it can grow.
  693.                 status = FHAddStyleRun(hFHRec, aStyle, runIndex);
  694.                 nrequire(status, failed_AddRun);
  695.                 HLock(hRuns);                                                                            // Lock it down again.
  696.  
  697.                 runLength = (short*)(*hRuns) + runIndex;                    // Point into it for incrementing run length.
  698.                 
  699.                 nrequire(status = FHSetStylePrFontIndex(aStyle, prFontIndex), failed_TagStyle);
  700.  
  701.                 lastPrIndex = prFontIndex;
  702.                 ++runIndex;
  703.                 *runLength  = 1;            
  704.  
  705.             } else {
  706.                                 
  707.                 *runLength += 1;
  708.                 
  709.             }//end if
  710.             
  711.             ++pGlyphs;
  712.         
  713.         }//end for
  714.         
  715.         
  716.         /*** If more than one run was generated, make it a glyph shape ****/
  717.         
  718.         if (runIndex > 1) {
  719.             
  720.             gxStyle                 *pStyle;
  721.             register short idx;
  722.             
  723.             hStyles = (*hFHRec)->workHandle[kStyleHandle];
  724.             hRuns = (*hFHRec)->workHandle[kRunHandle];
  725.             
  726.             HLock(hStyles);
  727.             
  728.             GXSetShapeType(theShape, gxGlyphType);
  729.             
  730.             GXSetGlyphParts(theShape, 1, charCount, charCount, nil, nil, nil, nil,
  731.                                                 (short*)*hRuns, (gxStyle*)*hStyles);
  732.             nrequire(status = GXGetGraphicsError(nil), failed_SetGlyphParts);
  733.             
  734.             /** dispose of the styles we created **/
  735.             pStyle = (gxStyle*)*hStyles;
  736.             for (idx = runIndex - 1; idx >= 0; --idx)
  737.                 GXDisposeStyle(*pStyle++);
  738.         
  739.         } else {        // couldn't have even cloned it if 
  740.         
  741.             GXDisposeStyle(theStyle);                // we cloned it.
  742.         
  743.         }//end if
  744.         
  745.         /** Tag the shape with the new text and bits **/
  746.  
  747.         /** The 1or2 byte code bits are unnecessary if we left it a text shape, pass nil **/
  748.         if (runIndex <= 1)
  749.             pTwoByteGlyphBits = nil;
  750.             
  751.         status = FHSetTextTag(theShape, (unsigned char*)*newGlyphs, dataSize, pTwoByteGlyphBits, charCount);
  752.         ncheck(status);
  753.  
  754. failed_SetGlyphParts:
  755. failed_TagStyle:
  756. failed_AddRun:
  757. failed_MapGlyph:
  758. failed_InitStyle:
  759.  
  760.         FHReleaseWorkspace(hFHRec, kStyleHandle);
  761.         FHReleaseWorkspace(hFHRec, kRunHandle);
  762.         FHReleaseWorkspace(hFHRec, kTextHandle);
  763.         if (thePlatform != gxGlyphPlatform) FHReleaseWorkspace(hFHRec, kGlyphHandle);
  764.         FHReleaseWorkspace(hFHRec, kEncodedGlyphHandle);
  765.  
  766.  
  767. failed_SetSize2:
  768. failed_SetSize1:    
  769. failed_FHGetFont:
  770.         
  771.         return(status);
  772.         
  773.     }//FHResolveTextShape
  774.  
  775.  
  776. //<FF>
  777. /*************************************************
  778.  
  779.     Function: FHResolveLayoutShape
  780.     
  781.     Resolve the codes and fonts for a layout shape.
  782.     
  783. **************************************************/
  784. OSErr    FHResolveLayoutShape(TFontHandlerHdl hFHRec, gxShape theShape);
  785. OSErr    FHResolveLayoutShape(TFontHandlerHdl hFHRec, gxShape theShape)
  786.     {
  787.         OSErr                        status;
  788.         gxShapeType            newType;
  789.         /**********
  790.             Call PrimitiveShape to get a glyph shape that has layout stuff applied to it.
  791.             SetShapeType(theShape, glyphType) would just convert the geometry to a glyph
  792.             without applying justification or contextual forms, etc…  Note:  If PrimitiveShape
  793.             on a layout ever changes to not make a shape of type glyph, this and the PostScript
  794.             Imaging Engine will break, since the IE is also dependent on glyph shapes being
  795.             generated.
  796.         **********/
  797.         GXPrimitiveShape(theShape);
  798.         nrequire(status = GXGetGraphicsError(nil), failed_ChangeType);
  799.  
  800.  
  801.         newType = GXGetShapeType(theShape);        
  802.         if (newType == gxEmptyType) {
  803.         
  804.             status = noErr;                                                        // Just return.        
  805.         
  806.         } else if (newType == gxGlyphType) {                // Resolve the glyph shape.
  807.  
  808.             status = FHResolveGlyphShape(hFHRec, theShape);
  809.             
  810.         } else {                                                                    // This should never happen, should always be glyph or empty.
  811.         
  812. #if DEBUGLEVEL > 0
  813.             dprintf(notrace, "PrimitiveShape on layout did not generate glyph or empty shape. Fatal Error!!!!");
  814. #endif
  815.             status = illegal_type_for_shape;
  816.                     
  817.         }//end if
  818.  
  819. failed_ChangeType:    
  820.         ncheck(status);
  821.         return(status);
  822.         
  823.     }//FHResolveLayoutShape
  824.  
  825.  
  826. //<FF>
  827. #if useDEBUGTEXT
  828. /*******************************
  829.     Routine: FHShowDebugText
  830.     
  831.     Routine outputs a PostScript comment that
  832.     shows the text of the shape that is about
  833.     to be resolved in its un-printer encoeded 
  834.     form so the PostScript file is more readable.
  835.     
  836.     This code is only in the debugging version
  837.     
  838. ********************************/
  839. OSErr FHShowDebugText(TFontHandlerHdl hFHRec, gxShape theShape)
  840.     {
  841.         OSErr                    status;    
  842.         TRDParams            rdParams;
  843.         unsigned char    *textData;
  844.         long                    byteCount;
  845.         
  846.         rdParams.rdMap = (*hFHRec)->rdMap;
  847.         rdParams.resType = kScriptResType;
  848.         rdParams.resID = kFHScriptResID;
  849.         rdParams.rdFlags = eRDnoOptions;
  850.         rdParams.resIndex = kDebugShowText;
  851.         
  852.         switch(GXGetShapeType(theShape)) {
  853.         
  854.             case gxTextType:
  855.                 byteCount = GXGetText(theShape, nil, nil, nil);
  856.                 nrequire(status = PrNewPtr(&textData, byteCount), failed_Alloc);
  857.                 GXGetText(theShape, nil, textData, nil);
  858.                 break;
  859.                 
  860.             case gxLayoutType:
  861.                 byteCount = GXGetLayout(theShape, nil, nil, nil, nil, nil, nil, nil, nil, nil);
  862.                 nrequire(status = PrNewPtr(&textData, byteCount), failed_Alloc);
  863.                 GXGetLayout(theShape, textData, nil, nil, nil, nil, nil, nil, nil, nil);
  864.                 break;
  865.             
  866.             case gxGlyphType:        
  867.                 byteCount = GXGetGlyphs(theShape, nil, nil, nil, nil, nil, nil, nil, nil);
  868.                 nrequire(status = PrNewPtr(&textData, byteCount), failed_Alloc);
  869.                 GXGetGlyphs(theShape, nil, textData, nil, nil, nil, nil, nil, nil);
  870.                 break;
  871.         
  872.         }//end switch
  873.         
  874.         status = RDResPrintf(&rdParams, textData, byteCount);
  875.         ncheck(status);
  876.         
  877.         (void) PrDisposePtr(textData);
  878.  
  879. failed_Alloc:    
  880.         return(status);
  881.         
  882.     }//FHShowDebugText
  883. #endif
  884.  
  885. //<FF>
  886. /*************************************************
  887.  
  888.     Function:        FontHandlerResolveShapeFonts:
  889.     
  890.     Function remaps all of the glyph codes in a shape
  891.     to printer codes.  New style runs are generated if
  892.     necessary so that styles can be tagged with child font
  893.     indecies.
  894.     
  895.     context:            The font handler context.  (if nil, then we'll say no outline fonts are available signaling client to rasterize of pathify)
  896.     theShape:            Shape to resolve.
  897.     
  898. **************************************************/
  899. OSErr FontHandlerResolveShapeFonts(TFontHandlerContext context, gxShape theShape)
  900.     {
  901.         OSErr                        status;
  902.         gxShapeType            theType;
  903.         Boolean                    done = false;
  904.  
  905.         if (context == nil)    
  906.             return(no_outline_font_found);
  907.          
  908.         #if 0                    /*** DEBUGLEVEL > 1 ****/
  909.             status = FHShowDebugText((TFontHandlerHdl)context, theShape);
  910.             ncheck(status);
  911.             if (status != noErr) return(status);
  912.         #endif
  913.         
  914.  
  915.         while (!done) {
  916.         
  917.             theType = GXGetShapeType(theShape);
  918.             
  919.             switch(theType) {
  920.             
  921.                 case gxTextType:
  922.                     status = FHResolveTextShape((TFontHandlerHdl)context, theShape);
  923.                     break;    
  924.                 
  925.                 case gxGlyphType:
  926.                     status = FHResolveGlyphShape((TFontHandlerHdl)context, theShape);
  927.                     break;
  928.             
  929.                 case gxLayoutType:
  930.                     status = FHResolveLayoutShape((TFontHandlerHdl)context, theShape);
  931.                     break;
  932.                     
  933.                 default:
  934.                     status = noErr;
  935.             
  936.             }//end switch
  937.             
  938.     
  939.             /************************************************
  940.                 A Collection error indicates that the some glyph
  941.                 from the shape was not in any of the printer fonts.
  942.                 Build new printer fonts for this shape and try again.
  943.             **************************************************/
  944.             if ( (status == collectionItemNotFoundErr) || (status == collectionIndexRangeErr) ) {
  945.     
  946.                 #if DEBUGLEVEL > 1
  947.                 dprintf(trace, "Calling FHAddNonDatabaseShape");
  948.                 #endif
  949.                 status = FHAddNonDatabaseShape((TFontHandlerHdl)context, theShape);
  950.                 nrequire(status, failed_NonDatabase);
  951.                 
  952.             } else {
  953.             
  954.                 done = true;
  955.                 
  956.             }//end if
  957.             
  958.         }//end while
  959.                 
  960. failed_NonDatabase:
  961.         
  962.         ncheck(status);
  963.         return(status);
  964.         
  965.     }//FontHandlerResolveShapeFonts
  966.  
  967.